<template>
  <el-dialog
    ref="dialogRef"
    v-model="visible"
    :width="isMobile ? '95%' : '95%'"
    :close-on-click-modal="false"
    @close="handleClose"
    class="knowledge-preview-dialog"
    align-center
    :fullscreen="true"
    :show-close="false"
  >
    <template #header>
      <div class="dialog-header-custom">
        <span class="dialog-title">{{ file?.title || '文件预览' }}</span>
        <div class="dialog-header-actions">
          <el-button @click="handleDownload" type="primary" size="small">
            <el-icon><Download /></el-icon>
            下载
          </el-button>
          <el-button @click="handleClose" size="small">
            关闭
          </el-button>
        </div>
      </div>
    </template>
    <div v-loading="loading" ref="previewContainerRef" class="preview-container">
      <!-- PDF预览 -->
      <div v-if="previewType === 'pdf'" class="preview-pdf">
        <iframe
          :src="previewUrl"
          frameborder="0"
          class="pdf-iframe"
        ></iframe>
      </div>

      <!-- 图片预览 -->
      <div v-else-if="previewType === 'image'" class="preview-image">
        <img :src="previewUrl" :alt="file?.title" class="image-preview" />
      </div>

      <!-- 视频预览 -->
      <div v-else-if="previewType === 'video'" class="preview-video">
        <video :src="previewUrl" controls class="video-preview">
          您的浏览器不支持视频播放
        </video>
      </div>

      <!-- 音频预览 -->
      <div v-else-if="previewType === 'audio'" class="preview-audio">
        <div class="audio-container">
        <div class="audio-info">
          <el-icon class="audio-icon"><Headset /></el-icon>
          <span class="audio-title">{{ file?.title }}</span>
        </div>
          <audio :src="previewUrl" controls class="audio-player">
            您的浏览器不支持音频播放
          </audio>
        </div>
      </div>

      <!-- 文本预览 -->
      <div v-else-if="previewType === 'text'" class="preview-text">
        <div class="text-preview-header">
          <div class="header-left">
            <el-tag v-if="file?.format === 'md'" type="info">Markdown</el-tag>
            <el-tag v-else-if="file?.format === 'html'" type="warning">HTML</el-tag>
            <el-tag v-else type="success">文本</el-tag>
            <span v-if="textContent" class="content-length">{{ textContent.length }} 字符</span>
          </div>
          <el-button
            v-if="isEditable"
            type="primary"
            size="small"
            @click="handleEdit"
            class="edit-btn"
          >
            <el-icon><Edit /></el-icon>
            编辑
          </el-button>
        </div>
        <div class="text-preview-content">
          <!-- 空内容提示 -->
          <div v-if="!loading && !textContent" class="empty-content">
            <el-empty description="文件内容为空" :image-size="100">
              <el-button v-if="isEditable" type="primary" @click="handleEdit">编辑文件</el-button>
            </el-empty>
          </div>
          <!-- Markdown渲染 -->
          <div v-else-if="file?.format === 'md' && textContent" class="markdown-preview" v-html="renderedMarkdown"></div>
          <!-- HTML渲染 -->
          <div v-else-if="file?.format === 'html' && textContent" class="html-preview" v-html="textContent"></div>
          <!-- 普通文本 -->
          <pre v-else-if="textContent" class="text-preview">{{ textContent }}</pre>
        </div>
      </div>

      <!-- Excel表格预览 -->
      <div v-else-if="previewType === 'excel'" class="preview-excel">
        <VueOfficeExcel
          v-if="fileData"
          :src="fileData"
          class="office-preview-content"
          @rendered="handleExcelRendered"
          @error="handleExcelError"
        />
        <div v-else class="excel-loading">
          <el-icon class="is-loading"><Loading /></el-icon>
          <span>正在加载表格...</span>
        </div>
      </div>

      <!-- Word文档预览 -->
      <div v-else-if="previewType === 'word'" class="preview-word">
        <VueOfficeDocx
          v-if="fileData"
          :src="fileData"
          class="office-preview-content"
          @rendered="handleWordRendered"
          @error="handleWordError"
        />
        <div v-else class="word-loading">
          <el-icon class="is-loading"><Loading /></el-icon>
          <span>正在加载文档...</span>
        </div>
      </div>

      <!-- PowerPoint预览 -->
      <div v-else-if="previewType === 'ppt'" class="preview-ppt">
        <VueOfficePptx
          v-if="fileData"
          :src="fileData"
          class="office-preview-content"
          @rendered="handlePptRendered"
          @error="handlePptError"
        />
        <div v-else class="ppt-loading">
          <el-icon class="is-loading"><Loading /></el-icon>
          <span>正在加载演示文稿...</span>
        </div>
      </div>

      <!-- 默认URL预览 -->
      <div v-else class="preview-default">
        <div class="default-notice">
          <el-alert
            type="warning"
            :closable="false"
            show-icon
          >
            <template #title>
              <div class="default-notice-content">
                <p>此文件类型不支持在线预览，请下载后查看。</p>
                <el-button type="primary" @click="handleDownload">下载文件</el-button>
              </div>
            </template>
          </el-alert>
        </div>
      </div>
    </div>
  </el-dialog>
</template>

<script setup lang="ts">
import { ref, computed, watch, onMounted, onUnmounted, nextTick } from 'vue'
import { ElMessage } from 'element-plus'
import { Edit, Download, Headset, Loading } from '@element-plus/icons-vue'
import { useWindowSize } from '@vueuse/core'
import { getKnowledgeFilePreview, getKnowledgeFileContent, downloadKnowledgeFile } from '@/api/knowledge'
import type { KnowledgeFile } from '@/api/knowledge'
import { marked } from 'marked'
import VueOfficeExcel from '@vue-office/excel'
import VueOfficeDocx from '@vue-office/docx'
import VueOfficePptx from '@vue-office/pptx'
import '@vue-office/excel/lib/index.css'
import '@vue-office/docx/lib/index.css'
// @vue-office/pptx 可能不需要单独的 CSS 导入

interface Props {
  modelValue: boolean
  fileId?: string
  file?: KnowledgeFile
}

interface Emits {
  (e: 'update:modelValue', value: boolean): void
  (e: 'edit', file: KnowledgeFile): void
}

const props = defineProps<Props>()
const emit = defineEmits<Emits>()

const visible = computed({
  get: () => props.modelValue,
  set: (val) => emit('update:modelValue', val)
})

// 响应式设计
const { width: windowWidth } = useWindowSize()
const isMobile = computed(() => windowWidth.value < 768)

const loading = ref(false)
const previewUrl = ref('')
const previewType = ref<'text' | 'pdf' | 'image' | 'excel' | 'word' | 'ppt' | 'video' | 'audio' | 'url'>('url')
const isEditable = ref(false)
const textContent = ref('')
const file = ref<KnowledgeFile | null>(null)
const fileData = ref<ArrayBuffer | null>(null)
const previewContainerRef = ref<HTMLElement | null>(null)
const dialogRef = ref<any>(null)

// 渲染Markdown
const renderedMarkdown = computed(() => {
  if (textContent.value && props.file?.format === 'md') {
    try {
      return marked(textContent.value)
    } catch (e) {
      return textContent.value
    }
  }
  return ''
})

// 加载预览信息
const loadPreview = async () => {
  if (!props.fileId && !props.file) return

  loading.value = true
  try {
    const fileId = props.fileId || props.file?.id
    if (!fileId) return

    const response = await getKnowledgeFilePreview(fileId)
    const data = response.data.data

    previewUrl.value = data.preview_url
    previewType.value = data.preview_type
    isEditable.value = data.is_editable
    file.value = data.file

    console.log('预览信息:', {
      fileId,
      previewType: data.preview_type,
      fileFormat: data.file?.format,
      isEditable: data.is_editable
    })

    // 根据预览类型加载相应的内容
    // 注意：严格按照预览类型处理，避免误判
    
    // 1. 文本类型：加载文本内容
    if (data.preview_type === 'text') {
      try {
        const contentResponse = await getKnowledgeFileContent(fileId)
        const content = contentResponse.data.data?.content || ''
        textContent.value = content
        // 如果内容为空，显示提示
        if (!content) {
          console.warn('文件内容为空')
        }
      } catch (e: any) {
        console.error('加载文件内容失败:', e)
        // 如果是400错误（不支持编辑），说明后端判断有误，文件格式实际不支持文本预览
        // 这种情况下，使用URL预览方式
        if (e?.response?.status === 400) {
          console.warn('文件格式不支持文本预览，回退到URL预览')
          // 文件格式不支持文本预览，回退到URL预览
          previewType.value = 'url'
          // 清除文本内容
          textContent.value = ''
        } else if (e?.response?.status === 404) {
          // 文件不存在或已删除
          ElMessage.error('文件不存在或已被删除')
          textContent.value = ''
        } else {
          // 其他错误，显示警告
          ElMessage.warning('加载文件内容失败: ' + (e?.response?.data?.message || e?.message || '未知错误'))
          textContent.value = ''
        }
      }
    }
    // 2. Office文件（Excel、Word、PPT）：下载文件数据用于预览
    else if (['excel', 'word', 'ppt'].includes(data.preview_type)) {
      try {
        const response = await downloadKnowledgeFile(fileId)
        // 确保数据是 ArrayBuffer 格式
        if (response.data instanceof ArrayBuffer) {
          fileData.value = response.data
        } else if (response.data instanceof Blob) {
          // 如果是 Blob，转换为 ArrayBuffer
          fileData.value = await response.data.arrayBuffer()
        } else {
          // 如果是其他格式，尝试转换
          const blob = new Blob([response.data])
          fileData.value = await blob.arrayBuffer()
        }
      } catch (e: any) {
        console.error('加载Office文件失败:', e)
        ElMessage.error('加载文件失败，请尝试下载后查看')
        // 回退到URL预览
        previewType.value = 'url'
      }
    }
    // 3. 其他类型（PDF、图片、视频、音频等）：使用 preview_url 直接预览
    // 不需要额外处理，直接使用 previewUrl
  } catch (error: any) {
    console.error('加载预览失败:', error)
    ElMessage.error('加载预览失败: ' + (error?.message || '未知错误'))
  } finally {
    loading.value = false
  }
}

// 编辑文件
const handleEdit = () => {
  if (file.value) {
    emit('edit', file.value)
  }
}

// 下载文件
const handleDownload = async () => {
  const fileId = props.fileId || props.file?.id
  if (!fileId) return

  try {
    const response = await downloadKnowledgeFile(fileId)
    const blob = new Blob([response.data])
    const url = window.URL.createObjectURL(blob)
    const link = document.createElement('a')
    link.href = url
    link.download = file.value?.filename || 'file'
    link.click()
    window.URL.revokeObjectURL(url)
    ElMessage.success('下载成功')
  } catch (error) {
    console.error('下载失败:', error)
    ElMessage.error('下载失败')
  }
}

// Office文件渲染完成
const handleExcelRendered = () => {
  console.log('Excel渲染完成')
}

const handleWordRendered = () => {
  console.log('Word渲染完成')
}

const handlePptRendered = () => {
  console.log('PPT渲染完成')
}

// Office文件渲染错误
const handleExcelError = (error: any) => {
  console.error('Excel渲染失败:', error)
  ElMessage.warning('表格预览失败，请尝试下载后查看')
}

const handleWordError = (error: any) => {
  console.error('Word渲染失败:', error)
  ElMessage.warning('文档预览失败，请尝试下载后查看')
}

const handlePptError = (error: any) => {
  console.error('PPT渲染失败:', error)
  ElMessage.warning('演示文稿预览失败，请尝试下载后查看')
}


// 关闭对话框
const handleClose = () => {
  visible.value = false
  previewUrl.value = ''
  previewType.value = 'url'
  textContent.value = ''
  file.value = null
  fileData.value = null
}

// 监听对话框打开/关闭，加载预览
watch(visible, (val) => {
  if (val) {
    // 加载预览
    loadPreview()
  }
})

// 监听文件变化
watch(() => props.fileId, () => {
  if (visible.value) {
    loadPreview()
  }
})

// 组件卸载时清理
onUnmounted(() => {
  // 清理工作
})
</script>

<style scoped lang="scss">
.knowledge-preview-dialog {
  :deep(.el-dialog__header) {
    padding: 16px 20px;
    border-bottom: 1px solid var(--el-border-color-light);
  }

  .dialog-header-custom {
    display: flex;
    align-items: center;
    justify-content: space-between;
    width: 100%;
    padding-right: 0;
  }

  .dialog-title {
    font-size: 18px;
    font-weight: 600;
    color: var(--el-text-color-primary);
    flex: 1;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }

  .dialog-header-actions {
    display: flex;
    align-items: center;
    gap: 12px;
    flex-shrink: 0;
    margin-left: 20px;
  }

  :deep(.el-dialog__body) {
    padding: 0;
    height: calc(100vh - 60px);
    overflow: hidden;
  }

  .preview-container {
    min-height: 400px;
    height: 100%;
    overflow: auto;
  }

  .preview-pdf {
    width: 100%;
    height: 75vh;
    transition: height 0.3s ease;

    .pdf-iframe {
      width: 100%;
      height: 100%;
    }
  }

  .preview-image {
    display: flex;
    justify-content: center;
    align-items: center;
    min-height: 400px;

    .image-preview {
      max-width: 100%;
      max-height: 75vh;
      object-fit: contain;
      transition: max-height 0.3s ease;
    }
  }

  .preview-video {
    display: flex;
    justify-content: center;
    align-items: center;
    min-height: 400px;

    .video-preview {
      max-width: 100%;
      max-height: 75vh;
      transition: max-height 0.3s ease;
    }
  }

  .preview-audio {
    display: flex;
    justify-content: center;
    align-items: center;
    min-height: 300px;
    padding: 40px;

    .audio-container {
      width: 100%;
      max-width: 600px;

      .audio-info {
        display: flex;
        align-items: center;
        gap: 12px;
        margin-bottom: 20px;

        .audio-icon {
          font-size: 32px;
          color: var(--el-color-primary);
        }

        .audio-title {
          font-size: 18px;
          font-weight: 500;
        }
      }

      .audio-player {
        width: 100%;
      }
    }
  }

  .preview-text {
    display: flex;
    flex-direction: column;
    height: 100%;
    overflow: hidden;

    .text-preview-header {
      display: flex;
      justify-content: space-between;
      align-items: center;
      padding: 16px 20px;
      border-bottom: 1px solid var(--el-border-color);
      background: #fff;
      flex-shrink: 0;

      .header-left {
        display: flex;
        align-items: center;
        gap: 12px;

        .content-length {
          font-size: 12px;
          color: var(--el-text-color-secondary);
        }
      }

      .edit-btn {
        margin-left: auto;
      }
    }

      .text-preview-content {
      flex: 1;
      overflow: auto;
      padding: 0;
      background: #f5f7fa;
      min-height: 0;

      .empty-content {
        display: flex;
        justify-content: center;
        align-items: center;
        height: 100%;
        min-height: 400px;
      }

      .markdown-preview {
        padding: 24px 32px;
        background: #fff;
        line-height: 1.8;
        max-width: 1200px;
        margin: 0 auto;
        min-height: 100%;

        :deep(h1),
        :deep(h2),
        :deep(h3) {
          margin-top: 24px;
          margin-bottom: 16px;
          font-weight: 600;
        }

        :deep(p) {
          margin-bottom: 16px;
        }

        :deep(code) {
          background: #f5f5f5;
          padding: 2px 6px;
          border-radius: 3px;
          font-family: 'Courier New', monospace;
        }

        :deep(pre) {
          background: #f5f5f5;
          padding: 16px;
          border-radius: 4px;
          overflow-x: auto;
        }

        :deep(blockquote) {
          border-left: 4px solid #ddd;
          padding-left: 16px;
          margin: 16px 0;
          color: #666;
        }
      }

      .html-preview {
        padding: 24px 32px;
        background: #fff;
        min-height: 100%;
        max-width: 1200px;
        margin: 0 auto;
      }

      .text-preview {
        padding: 24px 32px;
        background: #fff;
        font-family: 'Courier New', monospace;
        white-space: pre-wrap;
        word-wrap: break-word;
        margin: 0 auto;
        min-height: 100%;
        max-width: 1200px;
        line-height: 1.6;
      }
    }
  }

  .preview-excel,
  .preview-word,
  .preview-ppt {
    width: 100%;
    height: 100%;
    display: flex;
    justify-content: center;
    align-items: center;
    flex: 1 1 auto;
    min-height: 0;

    .office-preview-content {
      height: 100%;
      width: 100%;
      flex: 1 1 auto;
      min-height: 0;
    }

    .excel-loading,
    .word-loading,
    .ppt-loading {
      display: flex;
      flex-direction: column;
      align-items: center;
      gap: 12px;
      color: var(--el-text-color-secondary);

      .el-icon {
        font-size: 32px;
      }
    }
  }

  .preview-default {
    display: flex;
    justify-content: center;
    align-items: center;
    min-height: 400px;

    .default-notice {
      width: 100%;
      max-width: 600px;

      .default-notice-content {
        display: flex;
        justify-content: space-between;
        align-items: center;
        width: 100%;

        p {
          margin: 0;
          flex: 1;
        }
      }
    }
  }

}

// 全屏对话框样式（Element Plus 的 fullscreen 属性）
.knowledge-preview-dialog {
  :deep(.el-dialog) {
    &.is-fullscreen {
      width: 100vw !important;
      height: 100vh !important;
      max-width: 100vw !important;
      max-height: 100vh !important;
      margin: 0 !important;
      border-radius: 0 !important;
      display: flex !important;
      flex-direction: column !important;
    }
  }

  :deep(.el-dialog__header) {
    flex-shrink: 0 !important;
    padding: 16px 20px !important;
    border-bottom: 1px solid var(--el-border-color-light) !important;
  }

  :deep(.el-dialog__body) {
    flex: 1 1 auto !important;
    padding: 0 !important;
    margin: 0 !important;
    overflow: hidden !important;
    display: flex !important;
    flex-direction: column !important;
    min-height: 0 !important;
    height: calc(100vh - 60px) !important;
  }

  .preview-container {
    flex: 1 1 auto !important;
    max-height: none !important;
    height: 100% !important;
    min-height: 0 !important;
    overflow: hidden !important;
    display: flex !important;
    flex-direction: column !important;
  }

  .preview-pdf {
    flex: 1 1 auto !important;
    height: 100% !important;
    min-height: 0 !important;

    .pdf-iframe {
      width: 100% !important;
      height: 100% !important;
    }
  }

  .preview-excel,
  .preview-word,
  .preview-ppt {
    flex: 1 1 auto !important;
    height: 100% !important;
    min-height: 0 !important;
    display: flex !important;
    flex-direction: column !important;

    .office-preview-content {
      flex: 1 1 auto !important;
      height: 100% !important;
      width: 100% !important;
      min-height: 0 !important;
    }
  }

  .preview-image,
  .preview-video {
    flex: 1 1 auto !important;
    height: 100% !important;
    min-height: 0 !important;
  }

  .preview-text {
    flex: 1 1 auto !important;
    display: flex !important;
    flex-direction: column !important;
    min-height: 0 !important;
    height: 100% !important;
    overflow: hidden !important;

    .text-preview-header {
      flex-shrink: 0 !important;
    }

    .text-preview-content {
      flex: 1 1 auto !important;
      max-height: none !important;
      overflow: auto !important;
      min-height: 0 !important;
      display: flex !important;
      flex-direction: column !important;

      .markdown-preview,
      .html-preview,
      .text-preview {
        flex: 1 1 auto !important;
        min-height: 100% !important;
      }

      .empty-content {
        flex: 1 1 auto !important;
        display: flex !important;
        justify-content: center !important;
        align-items: center !important;
      }
    }
  }
}
</style>

